package com.cms.interceptor;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.ibatis.binding.MapperMethod.ParamMap;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement; 
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature; 

import com.cms.common.CmsClassUtils;
import com.cms.common.RegUtils;
import com.cms.common.SiteUtil;
import com.cms.common.SpringContextBean;
import com.cms.common.StringUtils;
import com.cms.common.annotation.RecordLog;
import com.cms.model.BaseModel;
import com.cms.model.SysOperLog;
import com.cms.model.TrAdminUser;
import com.cms.service.SysOperLogService;

@Intercepts({@Signature(args = {MappedStatement.class, Object.class}, method = "update", type = Executor.class)})  
public class RecordLogInterceptor implements Interceptor{

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		String method =invocation.getMethod().getName(); 
		if(StringUtils.equals(method, "update"))
		{
			  MappedStatement statement =(MappedStatement)invocation.getArgs()[0]; 
			  String id=statement.getId();
			  String cls =StringUtils.substring(id, 0,id.lastIndexOf("."));
			  String invoke =StringUtils.substring(id, id.lastIndexOf(".")+1); 
			  SqlCommandType sct=statement.getSqlCommandType();
			  Object obj = invocation.getArgs()[1];
			  final ParamMap map =(ParamMap)obj;
			  final Object target= map.get("param1"); 
			  Method m=CmsClassUtils.getMethodIgnoreParam(CmsClassUtils.getClass(cls),invoke);
			  RecordLog log=  m.getAnnotation(RecordLog.class);
			  if(log!=null)
			  {
				  SysOperLogService logService=SpringContextBean.getAppContext().getBean(SysOperLogService.class);
				  SysOperLog operLog = new SysOperLog();
				  TrAdminUser user = SiteUtil.getCurrentUser();
				  operLog.setUname(user.getUserName());
				  operLog.setUid(user.getId());
				  operLog.setActionIp(SiteUtil.getActionAddr());
				  operLog.setCatalog(log.catalog());
				  String expression=log.expression();//获取记录的表达式 
				  if(target instanceof BaseModel)//baseModel类型参数
				  {
					  String desc =RegUtils.findAndReplace("\\$\\{\\s*[a-zA-Z\\.0-9\\_\\-\\?\\*\\/]+\\}\\s*", expression, new RegUtils.FindCallback() {
						@Override
						public String execute(String paramString) { 
								String fname =StringUtils.substring(paramString, 2,paramString.length()-1);
								Object result =CmsClassUtils.getFieldValue(target, fname);
								if(result==null)
								{
									return StringUtils.EMPTY;
								}
								return StringUtils.obj2String(result);
						} });
					  operLog.setRemark(desc);
					  operLog.setReferId(StringUtils.str2Int(CmsClassUtils.getFieldValue(target, log.id())+""));
					  operLog.setReferName(StringUtils.obj2String(CmsClassUtils.getFieldValue(target, log.name())));
				  }
				  else if(target instanceof Map)//map对象参数
				  {
					  final Map<String,Object> result=(Map)target;
					  String desc =RegUtils.findAndReplace("\\$\\{\\s*[a-zA-Z\\.0-9\\_\\-\\?\\*\\/]+\\}\\s*", expression, new RegUtils.FindCallback() {
							@Override
							public String execute(String paramString) { 
									String fname =StringUtils.substring(paramString, 2,paramString.length()-1);
									return result.get(fname)+"";
							} });
						  operLog.setRemark(desc);
						  operLog.setReferId(StringUtils.str2Int(result.get(log.id())+""));
						  operLog.setReferName(StringUtils.obj2String(result.get(log.name())));
				  }
				  else if(target instanceof List)
				  {
					  operLog.setRemark(log.expression()); 
				  }
				  else//多个参数类型
				  { 
					  String desc =RegUtils.findAndReplace("\\$\\{\\s*[a-zA-Z\\.0-9\\_\\-\\?\\*\\/]+\\}\\s*", expression, new RegUtils.FindCallback() {
							@Override
							public String execute(String paramString) { 
									String fname =StringUtils.substring(paramString, 2,paramString.length()-1);
									Object result =map.get(fname);
									if(result==null)
									{
										return StringUtils.EMPTY;
									}
									return StringUtils.obj2String(result);
							} });
						  operLog.setRemark(desc);
						  operLog.setReferId(StringUtils.str2Int(map.get(log.id())+""));
						  operLog.setReferName(StringUtils.obj2String(map.get(log.name())));
				  }
				  operLog.setType(sct.name());
				  logService.addSysOperLog(operLog);
			  }
		} 
		Object obj = invocation.proceed();
		return obj;
	}

	@Override
	public Object plugin(Object obj) {
		return Plugin.wrap(obj, this);
	}

	@Override
	public void setProperties(Properties pro) {
	}

}
